=begin rdoc
Determine Routing from a TOSSIM simulation file and write out detailed information

Author::    Matthias Woehrle  (mailto:matthias.woehrle@tik.ee.ethz.ch)
Copyright:: Copyright (c) 2008 ETH Zurich
License::   

TODO:

MISSING:

=end
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
sourcepath =  File.expand_path("/Users/matthias/Documents/ETH/tecdoc/woehrlem/paper/woehrlem2008_sensys_poster/trunk/src/tossim")

def supremum(vector1, vector2)
  return_vector = Hash.new
  if vector1.length != vector2.length
    $stderr.puts "error"
  else
    vector1.each do |key, value|
      return_vector[key] = value
      return_vector[key] = vector2[key] if value < vector2[key]
    end
  end
  return return_vector
end

def increment(hash, node)
  hash[node] += 1
  return hash.deep_clone
end

require "rupeas"
require "graphviz"

class Hash
  def deep_clone
     returnhash = Hash.new()
     self.each do |key, element|
       returnhash[key] = element
     end
     return returnhash
   end
   
  def my_to_s
   string = String.new
   self.each do |key, value|
    string += "#{key}=> #{value};"
   end
   return string
  end

  alias_method :old_to_s, :to_s
  alias_method :to_s, :my_to_s
end

Rupeas.new do

Type :senddone do
 with :name =>:seqNo, :fieldtype=> :periodic, :range => 0..255, :notification => :error
 with :name =>:origin, :fieldtype => :integer, :range => 0..100,:notification => :error
 with :name =>:destination, :fieldtype => :integer, :range => 0..100, :notification => :warning
 with :name =>:nodeid,:fieldtype=> :integer, :range => 0..100,:notification => :error
 with :name =>:time, :fieldtype => :float, :notification => :warning 
end

Type :receive do
 with :name =>:seqNo, :fieldtype=> :periodic, :range => 0..255, :notification => :error
 with :name =>:origin, :fieldtype => :integer, :range => 0..100,:notification => :error
 with :name =>:destination, :fieldtype => :integer, :range => 0..100, :notification => :warning
 with :name =>:nodeid,:fieldtype=> :integer, :range => 0..100,:notification => :error
 with :name =>:time, :fieldtype => :float, :notification => :warning 
end

filename = 'minuscule.log'
t=Time.new
monthdayhourmin = t.strftime("%y-%m-%d--%H%M")

all = loadlog(sourcepath + '/' + filename)

    
nodehash = Hash.new
totalset = EventSet.new
nodefiltered = EventSet.new
processedset = EventSet.new
    
[10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,0,43,44,45,46,100,48,49,50,51,52,53,
  54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79].each do |node|
    nodehash[node] = 0
end

[10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,0,43,44,45,46,100,48,49,50,51,52,53,
  54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79].each do |node|
     nodefiltered = all[:nodeid=>node].sort_by {|event| event[:time]}
     vector_temp = nodefiltered.predicate(1){|send| send[:type]==:receive or send[:type]==:senddone}
     vectorset = set_transform(vector_temp, :merge, 1) do |e1|
          {
            :type =>  e1[:type],
            :nodeid => e1[:nodeid],
            :destination => e1[:destination],
            :seqNo => e1[:seqNo],
            :origin => e1[:origin],
            :time => e1[:time],
            :hop_count => 0.5,
            :vector_time => increment(nodehash,node)
          }
     end
     processedset.merge(vectorset)
     #reset nodehash
     nodehash[node] = 0
     
  
     
end


[10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,0,43,44,45,46,100,48,49,50,51,52,53,
  54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79].each do |origin|
#[12,13,14].each do |origin|
  originfiltered = EventSet.new

  if processedset[:origin=>origin].length > 0
     originfiltered = processedset[:origin=>origin]
#     puts "------------\nProcessing #{originfiltered.length} events for origin #{origin}\n"
     
     
     
    all.values(:seqNo).each do |seqNo|
#     [67,68].each do |seqNo|
       
       #puts "------------\nProcessing #{originfiltered[:seqNo=>seqNo].length} events for origin #{origin} and sequence Number #{seqNo}\n"
       
       routestart_temp = originfiltered[:seqNo=>seqNo].predicate(1){|send| send[:origin] == send[:nodeid] and send[:type] == :senddone}
       routestart = set_transform(routestart_temp, :merge, 1) do |e1|
            [
              {
              :type => :transmission,
              :nodeid => e1[:nodeid],
              :destination => e1[:destination],
              :seqNo => e1[:seqNo],
              :origin => e1[:origin],
              :time => e1[:time],
              :path => e1[:nodeid].to_s,
              :hop_count => 0.5,
              :vector_time => e1[:vector_time]
            },
             {
              :type => e1[:type],
              :nodeid => e1[:nodeid],
              :destination => e1[:destination],
              :seqNo => e1[:seqNo],
              :origin => e1[:origin],
              :time => e1[:time],
              :vector_time => e1[:vector_time]
            }
          ]
       end
            
       packet_starts = routestart[:type=>:transmission].length
       resultset = routestart.iterative do |iteration|
          temp = iteration.predicate(2) {|e1, e2| e1[:origin] == e2[:origin]  and ((e1[:type] == :transmission and \
          e2[:type] == :receive and e1[:destination] == e2[:nodeid]) or (e1[:nodeid] == e2[:nodeid] and
          e1[:type] == :transmission and e2[:type] == :senddone) and (e1[:vector_time] != e2[:vector_time]))
          }
          iteration.set_transform(temp, :merge, 2) do |e1, e2|
          [
            {
            :nodeid => e2[:nodeid],
            :type => :transmission,
            :origin => e1[:origin],
            :destination => e2[:destination],
            :seqNo => e1[:seqNo],
            :time => e2[:time],
            :path => (e1[:path].to_s + '-' + e2[:nodeid].to_s),
            :hop_count => e1[:hop_count] + 0.5,
            :vector_time => supremum(e1[:vector_time], e2[:vector_time])            
            
          },
           {
            :type => e2[:type],
            :nodeid => e2[:nodeid],
            :destination => e2[:destination],
            :seqNo => e2[:seqNo],
            :origin => e2[:origin],
            :time => e2[:time],
            :vector_time => supremum(e1[:vector_time], e2[:vector_time])
          }
        ]
         end
       end
       totalset = totalset.merge(resultset)
       
    end

  end


end
  savelog(totalset, filename + monthdayhourmin + '.eventset')
end